package code11_util;

public class Test02 {

	public static void main(String[] args) {
		//t1();
		//t2();
		//t3();
		//t4();
		t5();
	}

	private static void t5() {
		Book b1 = new Book();
		b1.name = "小红帽";
		String sname = "jerry"; 
		Stu s1 = new Stu(1, sname, b1);
		System.out.println("s1:"+s1);
		try {
			Stu s2 = s1.clone();
			// 修改 s2 的 book name
			s2.book.name = "小红帽和大灰狼";
			System.out.println("s2:"+s2);
			// 浅克隆时s1 的 book name 也被修改了
			// 深克隆时s1 的 book name 不会被修改
			System.out.println("s1:"+s1);
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

	private static void t4() {
		User u1 = new User(20, "tom");
		//User u2 = u1; // 引用赋值
		try {
			User clone = u1.clone();
			System.out.println(clone);
			System.out.println(u1 == clone);// false
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

	private static void t3() {
		User u1 = new User(20, "tom");
		// 默认会调用 对象的 toString
		System.out.println(u1);
		
		u1 = null;
	}

	private static void t2() {
		User u1 = new User(20, "tom");
		User u2 = new User(20, "tom");
		System.out.println("u1.hashCode="+u1.hashCode());
		System.out.println("u2.hashCode="+u2.hashCode());
	}

	private static void t1() {
		User u1 = new User(20, "tom");
		User u2 = new User(20, "tom");
		User u3 = u1;// 把栈中保存的 地址 赋值给了 u3
		// == 比较, 比较的是栈中的值
		System.out.println(u1 == u2);// false, 堆中地址不同
		System.out.println(u1 == u3);// true, 堆中地址相同
		// equals 用于对象比较
		// 需要重写对象所在类的 equals方法
		System.out.println(u1.equals(u2));// true, id相同
		//System.out.println(u1.equals(null));
		//System.out.println(u1.equals("123"));
		System.out.println(u1.equals(u3));// true
	}
	
}
class User implements Cloneable {
	public int id;// 标识
	public String name;
	public User() {
	}
	public User(int id, String name) {
		this.id = id;
		this.name = name;
	}
	// 重写equals
//	@Override
//	public boolean equals(Object obj) {
//		if (null == obj) {
//			return false;
//		}
//		if (obj instanceof User) {
//			User u = (User) obj;
//			return this.id == u.id;
//		} else {
//			// 不是 User
//			return false;
//		}
//	}
//	@Override
//	public int hashCode() {
//		return id;
//	}
	// 一般通过工具自动生成 equals, hashCode
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		User other = (User) obj;
		if (id != other.id)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + "]";
	}
	@Override
	protected void finalize() throws Throwable {
		// 解除自身中的一些属性的引用。
		name = null;
	}
	// 一般把 protected 改为 public, 把 返回值类型 改为 被克隆的对象的类型
	@Override
	public User clone() throws CloneNotSupportedException {
		// 浅克隆
		// 必须调用父类的 clone 方法, 当前类 必须实现 java.lang.Cloneable 接口, 使当前类拥有被克隆的能力
		return (User) super.clone();
	}
}
class Book implements Cloneable {
	public String name;
	@Override
	public Book clone() throws CloneNotSupportedException {
		return (Book) super.clone();
	}
	@Override
	public String toString() {
		return "Book [name=" + name + "]";
	}
}
class Stu implements Cloneable {
	public int id;
	public String name;
	public Book book;
	public Stu(int id, String name, Book book) {
		this.id = id;
		this.name = name;
		this.book = book;
	}
//	@Override
//	public Stu clone() throws CloneNotSupportedException {
//		// 浅克隆
//		return (Stu) super.clone();
//	}
	@Override
	public Stu clone() throws CloneNotSupportedException {
		// 深克隆：需要程序员自己实现, 递归 克隆引用属性
		// 新进行浅克隆
		Stu s2 = (Stu) super.clone();
		// 再克隆内部的引用(依然使用浅克隆)
		Book b2 = this.book.clone();
		// 再把克隆好的引用对象，放回前面的初始的浅克隆出来的对象中
		s2.book = b2;
		return s2;
	}
	@Override
	public String toString() {
		return "Stu [id=" + id + ", name=" + name + ", book=" + book
				+ "]";
	}
}